import { ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { h, ref, Ref } from 'vue';
import LoginDialog from '@/components/LoginDialog.vue';
import { i18n } from '@/lang/index';
import eventBus from '@/utils/eventbus';
import ApiService from './ApiService';
import { ApiRequest } from './ApiRequest';
import { ApiResponse } from './ApiResponse';

// ApiClient用于前端交互，ApiService用于后台交互
class ApiClient {
  private static apiService = ApiService;
  private static loading = ElLoading.service({});

  public static async scanServer(callback: (result: string) => void): Promise<void> {
    try {
      await this.apiService.scanServer(callback);
    } catch (error) {
      ElMessage.error(i18n.global.t('scanFailed'));
    }
  }

  public static async connect(url: string): Promise<void> {
    this.loading = ElLoading.service({ fullscreen: true });
    if (this.apiService.checkStatus()) {
      ElMessage.warning(i18n.global.t('wsAlreadyConnected'));
      this.loading.close();
      return;
    }
  
    const isConnected = await this.apiService.connect(url);
    if (isConnected) {
      this.apiService.login((res) => {
        if (res.status === 200) {
          localStorage.setItem("key_info", res.data.key_name as unknown as string);
          localStorage.setItem("key_address", res.data.address as unknown as string);
          eventBus.emit('keyChange', res.data);
          ApiClient.loading.close();
          ElMessage.success(i18n.global.t('loginSuccess'));
        } else {
          ElMessage.error(i18n.global.t('loginFail'));
          this.showLogin();
        }
      });
    } else {
      ElMessage.error(i18n.global.t('connectFail'));
    }
  }

  public static disconnect(): void {
    this.apiService.disconnect();
  }

  public static checkStatus(): void {
    if(!this.apiService.checkStatus()){
      this.showLogin();
    }
  }

  public static showLogin() {
    const loginDialogRef: Ref<InstanceType<typeof LoginDialog> | null> = ref(null);

    ElMessageBox({
      title: i18n.global.t('login'),
      message: () =>
        h(LoginDialog, {
          onVnodeMounted: (vnode) => {
            loginDialogRef.value = vnode.component?.proxy as InstanceType<typeof LoginDialog> | null;
          },
        }),
      showConfirmButton: true,
      confirmButtonText: i18n.global.t('connect'),
      showClose: false,
      closeOnClickModal: false,
      closeOnPressEscape: true,
      customClass: 'login-dialog',
      confirmButtonClass: 'login-confirm-button',
      beforeClose: (action, instance, done) => {
        if (action === 'confirm') {
          const loginForm = loginDialogRef.value;
          if (loginForm) {
            const form = loginForm.form;
            this.connect(form.keyManagerAddress);
            done();
          } else {
            ElMessage.error(i18n.global.t('loginFailed'));
          }
        } else {
          done();
        }
      },
    });
  }

  public static sendSync(request: ApiRequest, callback: (response: ApiResponse) => void, timeout: number = 10000): void {
    if (!this.apiService.checkStatus()) {
      ElMessage.error(i18n.global.t('wsNotConnected'));
      return;
    }
    this.loading = ElLoading.service({});

    this.apiService.sendSync(request, (res) => {
      callback(res);
      this.loading.close();
    }, timeout);
  }

  public static sendSyncBackground(request: ApiRequest, callback: (response: ApiResponse) => void, timeout: number = 10000): void {
    if (!this.apiService.checkStatus()) {
      ElMessage.error(i18n.global.t('wsNotConnected'));
      return;
    }

    this.apiService.sendSync(request, (res) => {
      callback(res);
    }, timeout);
  }

  public static send(request: ApiRequest): void {
    if (!this.apiService.checkStatus()) {
      ElMessage.error(i18n.global.t('wsNotConnected'));
      return;
    }

    this.apiService.send(request);
  }

  
}

export default ApiClient;